package org.wang.chuangen.session.manager;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;

import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Session;
import org.apache.catalina.session.ManagerBase;
import org.apache.catalina.session.StandardSession;
import org.wang.chuangen.session.dao.RedisDao;
import org.wang.chuangen.session.db.RedisConn;
import org.wang.chuangen.session.util.Tool;
import org.wang.chuangen.session.vo.RedisSession;

/**
 * session管理器
 * @author 王传根
 * @date 2016-5-11下午1:15:55
 */
public class RedisSessionManager extends ManagerBase{

	/**
	 * 数据库链接单例
	 */
	private static final RedisConn REDIS_CONN=RedisConn.getInstance();
	
	/**
	 * 记录超时的session数量
	 */
	protected int rejectedSessions=0;
	
	/**
	 * 数据库持久层
	 */
	protected RedisDao redisDao=new RedisDao(REDIS_CONN);

	/**
	 * 设置数据库host
	 * @param host
	 * @author 王传根
	 * @date 2016-5-12上午10:29:19
	 */
	public void setHost(String host) {
		REDIS_CONN.setHost(host);
	}

	/**
	 * 设置数据库port
	 * @param port
	 * @author 王传根
	 * @date 2016-5-12上午10:29:34
	 */
	public void setPort(int port) {
		REDIS_CONN.setPort(port);
	}

	/**
	 * 设置数据库密码
	 * @param password
	 * @author 王传根
	 * @date 2016-5-12上午10:29:49
	 */
	public void setPassword(String password) {
		REDIS_CONN.setPassword(password);
	}
	
	/**
	 * session超时时间
	 * @param sessionTimeout
	 * @author 王传根
	 * @date 2016-8-25 下午7:50:26
	 */
	public void setSessionTimeout(int sessionTimeout) {
		REDIS_CONN.setSessionTimeout(sessionTimeout);
	}

	/**
	 * 超时时间
	 * @param timeout
	 * @author 王传根
	 * @date 2016-8-25 下午7:50:43
	 */
	public void setTimeout(int timeout) {
		REDIS_CONN.setTimeout(timeout);
	}
	
	/**
	 * 设置数据库
	 * @param database
	 * @author 王传根
	 * @date 2016-5-13下午9:16:50
	 */
	public void setDatabase(int database) {
		REDIS_CONN.setDatabase(database);
	}

	/**
	 * 设置序列化方式
	 * @param serialize
	 * @author 王传根
	 * @date 2016-5-13下午9:17:04
	 */
	public void setSerialize(String serialize) {
		REDIS_CONN.setSerialize(serialize);
	}

	/**
	 * 设置序列化编码
	 * @param charset
	 * @author 王传根
	 * @date 2016-5-13下午9:17:16
	 */
	public void setCharset(String charset) {
		try {
			REDIS_CONN.setCharset(Charset.forName(charset));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取超时的session数量
	 */
	@Override
	public int getRejectedSessions() {
		return rejectedSessions;
	}
	
	/**
	 * 生成新的sessionId
	 */
	@Override
	protected synchronized String generateSessionId() {
		String sessionId=super.generateSessionId();
		return redisDao.generateSessionId(sessionId);
	}

	/**
	 * session管理模块加载事件
	 */
	@Override
	public void load() throws ClassNotFoundException, IOException {
		Tool.fine("加载sesion管理器RedisSessionManager");
	}
	
	@Override
	protected void initInternal() throws LifecycleException {
		super.initInternal();
		try {
			REDIS_CONN.initialization();
			redisDao.initialization();
			Tool.fine("初始化session管理器");
		} catch (Exception e) {
			Tool.severe("初始化session管理器失败");
			e.printStackTrace();
		}
	}
	
	@Override
	protected void startInternal() throws LifecycleException {
		super.startInternal();
		setState(LifecycleState.STARTING);
	}

	@Override
	public Session createEmptySession() {
		Tool.fine("创建空session");
		return new RedisSession(this);
	}
	
	@Override
	protected StandardSession getNewSession() {
		return new RedisSession(this);
	}

	@Override
	public Session createSession(String sessionId) {
		Tool.fine("使用指定的sessionId创建session,sesssionId:"+sessionId);
		if(sessionId == null || sessionId.trim().length() == 0){
			sessionId=generateSessionId();
			Tool.fine("重新生成新的sessionId,sesssionId:"+sessionId);
		}
		Session session=createEmptySession();
		session.setId(sessionId);
		session.access();
		session.setNew(true);
		session.setValid(true);
		session.setCreationTime(System.currentTimeMillis());
		if(session instanceof StandardSession){
			StandardSession standardSession=(StandardSession)session;
			standardSession.tellNew();
		}
		if(redisDao.isSessionExist(sessionId)){
			redisDao.loadSession(session);
		}
		return session;
	}
	
	/**
	 * 新增session
	 */
	@Override
	public void add(Session session) {
		if(session == null)return;
		session.access();
		session.setValid(true);
		redisDao.saveSession(session);
		Tool.fine("sessionManager中新增session,sessionId:"+session.getId());
	}
	
	@Override
	public Session findSession(String sessionId) throws IOException {
		if(redisDao.isSessionExist(sessionId)){
			Session session=createEmptySession();
			session.access();
			session.setId(sessionId);
			session.setNew(false);
			session.setValid(true);
			redisDao.loadSession(session);
			return session;
		}
		return null;
	}
	
	@Override
	public HashMap<String, String> getSession(String sessionId) {
		return super.getSession(sessionId);
	}

	/**
	 * 删除session
	 */
	@Override
	public void remove(Session session) {
		remove(session, false);
	}
	
	@Override
	public void remove(Session session, boolean update) {
//		super.remove(session, update);
//		if(!update && session != null){
//			redisDao.removeSession(session.getId());
//		}
	}
	
	@Override
	protected void stopInternal() throws LifecycleException {
		super.stopInternal();
		REDIS_CONN.destroy();
		setState(LifecycleState.STOPPING);
		Tool.fine("卸载sesion管理器RedisSessionManager");
	}
	
	/**
	 * session管理器卸载事件
	 */
	@Override
	public void unload() throws IOException {
		REDIS_CONN.destroy();
	}

	@Override
	protected void finalize() throws Throwable {
		super.finalize();
	}
	
	
}
